/**
 * @file    If_can.c
 * @brief   驱动接口-CAN驱动接口
 * @author  name
 * @version 1.0.1
 * @date    2023-04-30
 * 
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2023-04-30 <td>1.0.1     <td>name     <td>首次创建
 * </table>
 */

/* includes ------------------------------------------------------------------*/
#include "If_can.h"
#include "drv_can.h"
/* macro/define --------------------------------------------------------------*/
#define  CAN_RECV_BUF_SIZE      (100)
/* typedef -------------------------------------------------------------------*/
typedef struct queue
{
   uint16_t head;      /*!< 队列头*/
   uint16_t tail;      /*!< 队列尾*/
   uint16_t free_size; /*!< 可用空间*/
   uint16_t cap_size;  /*!< 最大空间*/

   can_frame_type *data_buf;  /*!< 数据缓冲区域 */
}queue_can_type;

/* local functions -----------------------------------------------------------*/
static void queue_can_init(queue_can_type *queue , uint16_t size , can_frame_type *buff);
uint8_t queue_can_is_empty(const queue_can_type queue);
uint8_t queue_can_is_full(const queue_can_type queue);
void queue_can_in_fifo(uint8_t can_id ,const can_frame_type event_data);
uint8_t queue_can_out_fifo(queue_can_type *queue , can_frame_type *can_msg);
static void queue_can_clr_fifo(queue_can_type *queue);
/* static variables ----------------------------------------------------------*/
static can_frame_type can_recv_buff[IF_CAN_MAX][CAN_RECV_BUF_SIZE] = {0};   
static queue_can_type queue_can_recv_obj[IF_CAN_MAX] = {0};     

/* global variables ----------------------------------------------------------*/

/** ------------------------------------------------------------------------- *
  *                             Global function
 ** ------------------------------------------------------------------------- */\
void If_can_init(uint8_t can_id , uint32_t can_speed)
{
    if(can_id >= IF_CAN_MAX)
        return ;

    drv_can_init(can_id , can_speed);

    queue_can_init(&queue_can_recv_obj[can_id] , CAN_RECV_BUF_SIZE , can_recv_buff[can_id]);
    // 00 表示不屏蔽
	drv_can_set_rx_mb_mask(can_id , MSG(5) , CAN_STD_ID , 0x7FF , 0x00);

	drv_can_set_rx_mb_mask(can_id , MSG(6) , CAN_EXT_ID , 0x18F00102 , 0x00);
	
    drv_can_set_rx_cb_func(can_id , queue_can_in_fifo);
}

void If_can_send_frame(uint8_t can_id ,can_frame_type send_msg)
{
    if(can_id >= IF_CAN_MAX)
        return ;

    drv_can_send_frame(can_id, send_msg);
}

uint8_t If_can_read_one_frame(uint8_t can_id ,can_frame_type *recv_msg)
{
    if(can_id >= IF_CAN_MAX)
        return FALSE;

    if(FALSE == queue_can_is_empty(queue_can_recv_obj[can_id]))
    {
		queue_can_out_fifo(&queue_can_recv_obj[can_id] , recv_msg);
        return 1;
    }
	
    return 0;
}

void If_can_set_filter_mask(uint8_t can_id ,uint8_t rb_mb,uint8_t can_type, uint32_t filter_id , uint32_t mask)
{
    if(can_id >= IF_CAN_MAX)
        return ;

    drv_can_set_rx_mb_mask(can_id , rb_mb , can_type , filter_id , mask);
}

void If_can_clr_buf(uint8_t can_id)
{
    if(can_id >= IF_CAN_MAX)
        return ;
        
    queue_can_clr_fifo(&queue_can_recv_obj[can_id]);
}
/** ------------------------------------------------------------------------- *
  *                              Local function
 ** ------------------------------------------------------------------------- */
static void queue_can_init(queue_can_type *queue , uint16_t size , can_frame_type *buff)
{
   queue->head = 0;
   queue->tail = 0;
   queue->free_size = size;
   queue->cap_size = size;
   queue->data_buf = buff;
}

uint8_t queue_can_is_empty(const queue_can_type queue)
{
   if(queue.free_size == queue.cap_size)
      return TRUE;
   else
      return FALSE;
}

uint8_t queue_can_is_full(const queue_can_type queue)
{
   if(0 == queue.free_size)
      return TRUE;
   else
      return FALSE;
}

void queue_can_in_fifo(uint8_t can_id ,const can_frame_type can_msg)
{
    if(can_id >= IF_CAN_MAX)
        return ;
    
    queue_can_type *queue = &queue_can_recv_obj[can_id];

    if(TRUE == queue_can_is_full(*queue))
        return ;

    queue->data_buf[queue->head] = can_msg;

    if(queue->free_size > 0)
       -- queue->free_size;

    if(++ queue->head >= queue->cap_size)
      queue->head = 0;
}

uint8_t queue_can_out_fifo(queue_can_type *queue , can_frame_type *can_msg)
{
    if(queue->free_size < queue->cap_size)
    {
        *can_msg = *(queue->data_buf + queue->tail);
        ++ queue->free_size;

        if( ++ queue->tail >= queue->cap_size)
        queue->tail = 0;
	  
        return 1;
   }

   return 0;
}

static void queue_can_clr_fifo(queue_can_type *queue)
{
    queue->head = 0;
    queue->tail = 0;
    queue->free_size = queue->cap_size; 
}

/********** Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD *********/


